// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

package com.github.icedland.iced.x86.dec;

import com.github.icedland.iced.x86.Code;
import com.github.icedland.iced.x86.Instruction;
import com.github.icedland.iced.x86.OpKind;
import com.github.icedland.iced.x86.Register;

final class OpCodeHandler_D3NOW extends OpCodeHandlerModRM {
	private static final short[] s_codeValues = createCodeValues();

	private static short[] createCodeValues() {
		short[] result = new short[0x100];
		// GENERATOR-BEGIN: D3nowCodeValues
		// ⚠️This was generated by GENERATOR!🦹‍♂️
		result[0xBF] = Code.D3NOW_PAVGUSB_MM_MMM64;
		result[0xBB] = Code.D3NOW_PSWAPD_MM_MMM64;
		result[0xB7] = Code.D3NOW_PMULHRW_MM_MMM64;
		result[0xB6] = Code.D3NOW_PFRCPIT2_MM_MMM64;
		result[0xB4] = Code.D3NOW_PFMUL_MM_MMM64;
		result[0xB0] = Code.D3NOW_PFCMPEQ_MM_MMM64;
		result[0xAE] = Code.D3NOW_PFACC_MM_MMM64;
		result[0xAA] = Code.D3NOW_PFSUBR_MM_MMM64;
		result[0xA7] = Code.D3NOW_PFRSQIT1_MM_MMM64;
		result[0xA6] = Code.D3NOW_PFRCPIT1_MM_MMM64;
		result[0xA4] = Code.D3NOW_PFMAX_MM_MMM64;
		result[0xA0] = Code.D3NOW_PFCMPGT_MM_MMM64;
		result[0x9E] = Code.D3NOW_PFADD_MM_MMM64;
		result[0x9A] = Code.D3NOW_PFSUB_MM_MMM64;
		result[0x97] = Code.D3NOW_PFRSQRT_MM_MMM64;
		result[0x96] = Code.D3NOW_PFRCP_MM_MMM64;
		result[0x94] = Code.D3NOW_PFMIN_MM_MMM64;
		result[0x90] = Code.D3NOW_PFCMPGE_MM_MMM64;
		result[0x8E] = Code.D3NOW_PFPNACC_MM_MMM64;
		result[0x8A] = Code.D3NOW_PFNACC_MM_MMM64;
		result[0x87] = Code.D3NOW_PFRSQRTV_MM_MMM64;
		result[0x86] = Code.D3NOW_PFRCPV_MM_MMM64;
		result[0x1D] = Code.D3NOW_PF2ID_MM_MMM64;
		result[0x1C] = Code.D3NOW_PF2IW_MM_MMM64;
		result[0x0D] = Code.D3NOW_PI2FD_MM_MMM64;
		result[0x0C] = Code.D3NOW_PI2FW_MM_MMM64;
		// GENERATOR-END: D3nowCodeValues
		return result;
	}

	private final short[] codeValues = s_codeValues;

	@Override
	void decode(Decoder decoder, Instruction instruction) {
		instruction.setOp0Register(decoder.state_reg + Register.MM0);
		if (decoder.state_mod == 3)
			instruction.setOp1Register(decoder.state_rm + Register.MM0);
		else {
			instruction.setOp1Kind(OpKind.MEMORY);
			decoder.readOpMem(instruction);
		}
		int code = codeValues[decoder.readByte()];
		switch (code) {
		case Code.D3NOW_PFRCPV_MM_MMM64:
		case Code.D3NOW_PFRSQRTV_MM_MMM64:
			if ((decoder.options & DecoderOptions.CYRIX) == 0 || decoder.getBitness() == 64)
				code = Code.INVALID;
			break;
		}
		instruction.setCode(code);
		if (code == Code.INVALID)
			decoder.setInvalidInstruction();
	}
}
